# 找出一个文件夹里的所有图片，按照1,2,3,4,...的顺序命名，
# 并且把这些图片按照指定的大小进行裁剪。
import os
import shutil
from PIL import Image
# 修改名称。
def changeImagesName(_path):
    # 找出该路径（目录）下的所有带制定前缀的图片文件。
    # 下面代码中，lower() 是字符串对象的一个方法，它用于将字符串中的所有字符转换为小写形式。
    # 这个方法不会改变原始字符串，而是返回一个新的字符串，其中所有的大写字母都被转换为小写字母。
    # 可以使用 lower() 来确保用户输入的字符串与预期的字符串匹配，而不受大小写影响。
    images = [file for file in os.listdir(_path) if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp'))]

    # 找到每一个已获取的图片文件并按照数字顺序重命名。
    # enumerate()函数，它接受一个可迭代对象（这里是images列表）并返回一个生成器，
    # 生成一系列的元组，每个元组包含两个值。第一个值是索引，第二个值是从可迭代对象中获取的元素。
    # start = 1 表示索引从1开始编号。
    for number, previousName in enumerate(images, start = 1):
        # 获取文件拓展名。
        # 在下面代码中，os.path.splitext()函数将文件名拆分为文件名和文件扩展名，
        # 并返回一个包含两个元素的元组。第一个元素是文件名，第二个元素是文件扩展名。
        fileExtension = os.path.splitext(previousName)[1] # []内若改成数字0则代表获取文件名。
        
        # 创建新的文件名，例如 1，2，3 ...
        # 下面的代码使用了Python中的 f-string (格式化字符串字面值)，它允许在字符串中嵌入表达式。
        currentName = f"Genshin-{number}{fileExtension}" # 修改后的文件名和原来的拓展名

        # 构建完整的路径，包括先前的路径以及当前的路径。
        # 调用 os.path.join() 函数，该函数接受两个参数，将它们连接起来并返回一个新的路径字符串。
        # 在这里是将目录路径和文件名拼接而成的完整的文件路径。
        previousPath = os.path.join(_path, previousName)
        currentPath = os.path.join(_path, currentName)
        
        # 重命名文件。
        os.rename(previousPath, currentPath)
    
# 修改图片。
def modifyImages(_path, imageSize = (1920, 1080), imageRatio = (16, 9)):
    # 获取所有带指定前缀的图片文件。
    images = [file for file in os.listdir(_path) if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp'))]

    # 找到所有已经获取的图片文件并执行裁剪操作。
    for number, previousName in enumerate(images, start = 1):
        # 构建先前图片文件的路径。
        previousPath = os.path.join(_path, previousName)

        # 获取文件拓展名。
        fileExtension = os.path.splitext(previousName)[1]

        # 打开图片。
        # 下面代码中，Image.open() 方法用于打开指定路径的图片文件。它返回一个表示图像的 Image 对象。
        # as img 部分将打开的图像对象赋给一个变量 img，这样我们可以在 with 块中使用这个变量来引用打开的图像。
        # with ...:    是 Python 的 with 语句，用于创建一个上下文管理器。
        # 在这个上下文管理器中，我们可以执行一些操作，并确保在退出上下文时（即 with 块结束时）
        # 资源被正确地释放或关闭。对于文件处理，with 语句可以确保文件在使用完毕后被正确关闭。
        with Image.open(previousPath) as img:
            # 准备工作。
            # 下面代码中，调用了 Image 对象的 crop() 方法，用于裁剪图像。
            # crop() 方法接受一个包含左上角和右下角坐标的4元组，表示要裁剪的区域。

            # (0, 0) 表示裁剪的起始点是图像的左上角。
            # min(img.width, imageSize[0]) 表示裁剪的宽度为图像宽度和目标宽度之间的较小值。
            # min(img.height, imageSize[1]) 表示裁剪的高度为图像高度和目标高度之间的较小值。
            # 这样做的目的是确保裁剪的区域不超过图像的边界，同时限制裁剪的宽度和高度不超过目标尺寸 imageSize。

            # croppedImages = ...: 将裁剪后的图像保存在 croppedImages 变量中，以便后续的操作。
            # 计算裁剪的宽度和高度。
            previousWidth, previousHeight = img.size
            currentWidth = previousWidth
            currentHeight = int(currentWidth * imageRatio[1] / imageRatio[0])

            # 计算裁剪的开始(左上)和结束(右下)坐标。
            leftCoordinate = 0
            topCoordinate = (previousHeight - currentHeight) // 2
            rightCoordinate = previousWidth
            bottomCoordinate = topCoordinate + currentHeight

            # 开始裁剪。
            croppedImages = img.crop((leftCoordinate, topCoordinate, rightCoordinate, bottomCoordinate))

            # 开始缩放。
            zoomedImages = croppedImages.resize(imageSize)

            # 构建新的文件名。
            currentName = f"Shot {number:02d}{fileExtension}"

            # 构建新的文件完整路径。
            currentPath = os.path.join("output", currentName)

            # 保存修改后的图片。
            zoomedImages.save(currentPath)

# 将图片文件复制一份到当前目录。
def copyImages(_path):
    # 获取目录中所有图片文件。
    images = [file for file in os.listdir(_path) if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp'))]

    # 检索（遍历）所有图片文件。
    for previousName in images:
        # 构建先前图片文件的完整路径。
        previousPath = os.path.join(_path, previousName)

        # 构建新的文件名，为了防止文件名相同，在原文件名的前面加上前缀。
        temporaryName, fileExtension = os.path.splitext(previousName)
        currentName = f"_Genshin{temporaryName}{fileExtension}"

        # 构建新文件的完整路径。
        currentPath = os.path.join(_path, currentName)

        # 复制文件。
        # shutil是 Python 的标准库之一，提供了一些对文件和目录进行操作的工具函数。
        # copy2是 shutil 模块中的一个函数，用于复制文件，并尽量保留文件的元数据（例如修改时间等）。
        shutil.copy2(previousPath, currentPath)

if __name__ == "__main__":
    print("开始！！！")

    # 提供图片文件路径。
    imageFilePath = "input"

    # 执行文件复制操作。
    # copyImages(imageFilePath)

    # 执行文件重命名操作。
    # changeImagesName(imageFilePath)

    # 执行文件修改操作。
    modifyImages(imageFilePath)

    print("完成！！！")
